/*
 * @Author: january.cjy
 * @Date: 2021-09-27 19:18:39
 * @Last Modified by: january.cjy
 * @Last Modified time: 2021-11-02 19:47:10
 */
#include <CmgPPCallbacks.h>

#include "llvm/Support/raw_ostream.h"

namespace cmg {

using namespace llvm;
using namespace clang;

CmgPPCallbacks::CmgPPCallbacks(SourceManager &sm,FileFeature &feature) : sm(sm) ,fileFeature(feature){}

// #include
void CmgPPCallbacks::InclusionDirective(
    SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
    bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
    StringRef SearchPath, StringRef RelativePath, const clang::Module *Imported,
    SrcMgr::CharacteristicKind FileType) {
  //llvm::outs().changeColor(llvm::raw_ostream::RED);
  //llvm::outs() << "include directive: " << FileName << "\n";
  //llvm::outs().resetColor();
  return;
}

// 文件读写
void CmgPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,
                                 SrcMgr::CharacteristicKind FileType,
                                 FileID PrevFID) {
  return;
}

// 文件省略
void CmgPPCallbacks::FileSkipped(const FileEntryRef &SkippedFile,
                                 const Token &FilenameTok,
                                 SrcMgr::CharacteristicKind FileType) {
  return;
}

// 宏扩展
void CmgPPCallbacks::MacroExpands(const Token &MacroNameTok,
                                  const MacroDefinition &MD, SourceRange Range,
                                  const MacroArgs *Args) {
  
  return;
}

// 宏定义
void CmgPPCallbacks::MacroDefined(const Token &MacroNameTok,
                                  const MacroDirective *MD) {
  const MacroInfo* macroInfo=MD->getMacroInfo();
  unsigned int fid=sm.getFileID(sm.getSpellingLoc(macroInfo->getDefinitionLoc ())).getHashValue();
  std::string fileName=sm.getFilename(sm.getSpellingLoc(macroInfo->getDefinitionLoc ())).str();
  if(fileName!=""){
    std::string fileType = fileName.substr(fileName.find_last_of('.') + 1);
     if(fileFeature.isExist(fid)){
      fileFeature.getFeature(fid).macroDefine++;
    }else{
      //llvm::outs() << "macro define" << "\n";
      Feature feature(fid,fileName,fileType);
      feature.macroDefine++;
      fileFeature.addFeature(fid,feature);
    }
    
  }
  
  
  return;
}

// 宏解定义
void CmgPPCallbacks::MacroUndefined(const Token &MacroNameTok,
                                    const MacroDefinition &MD,
                                    const MacroDirective *Undef) {
  return;
}

// #if defined
void CmgPPCallbacks::Defined(const Token &MacroNameTok,
                             const MacroDefinition &MD, SourceRange Range) {
  return;
}

// #ifdef
void CmgPPCallbacks::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
                           const MacroDefinition &MD) {
  return;
}

// #ifndef
void CmgPPCallbacks::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
                            const MacroDefinition &MD) {
  return;
}

} // namespace cmg